
import util from '../util.js'
import * as dat from 'dat.gui';

class CesiumRainEffect {
  /**
   * 构造函数
   * @param {Cesium.Viewer} viewer - 已初始化的Cesium Viewer实例
   * @param {Object} options - 配置选项
   */
  constructor(viewer, options = {}) {
    if (typeof Cesium === 'undefined') {
      throw new Error('Cesium is not loaded. Please include Cesium.js before this script.');
    }

    // 验证viewer参数
    if (!(viewer instanceof Cesium.Viewer)) {
      throw new Error('First parameter must be a Cesium.Viewer instance');
    }

    if (typeof dat === 'undefined') {
      console.warn('dat.GUI is not loaded. No control panel will be available.');
    }

    // 保存viewer实例
    this.viewer = viewer;

    // 雨滴效果默认配置
    this.defaults = {
      // 改为位置数组，支持多个降雨区域
      positions: [
        Cesium.Cartesian3.fromDegrees(-104.99819046398898, 39.7518794202664, 20000),
        Cesium.Cartesian3.fromDegrees(-105.2, 39.8, 20000),  // 第二个点位
        Cesium.Cartesian3.fromDegrees(-104.8, 39.6, 20000),  // 第三个点位
        Cesium.Cartesian3.fromDegrees(-105.0, 39.9, 20000)   // 第四个点位
      ],
      activePositionIndex: 0,  // 添加默认的原点索
      rainConfig: {
        intensity: 0.8,        // 雨的强度
        speed: 15.0,           // 下落速度
        density: 0.02,         // 雨滴密度
        size: 1.2,             // 雨滴大小
        windX: 3.0,            // X方向风
        windY: 2.0,            // Y方向风
        range: 8000.0,         // 雨的范围
        height: 2000.0,        // 雨的高度
        streakLength: 15.0     // 雨滴拖尾长度
      },
      flyToDuration: 1
    };

    this.gui = null

    this.config = { ...this.defaults, ...options };
    this.rainConfig = { ...this.defaults.rainConfig, ...options.rainConfig };

    // 确保positions始终是数组
    if (!Array.isArray(this.config.positions)) {
      this.config.positions = [this.config.positions];
    }

    this.createRainEffect();

    if (typeof dat !== 'undefined') {
      this.createGuiControls();
    }

    this.flyToInitialPosition();
  }

  /**
   * 创建下雨效果
   */
  createRainEffect() {
    const shader = this.getRainShader();

    // 准备多个位置的逆矩阵
    const inverses = this.config.positions.map(position =>
      Cesium.Matrix4.inverse(
        Cesium.Transforms.eastNorthUpToFixedFrame(position),
        new Cesium.Matrix4()
      )
    );

    this.postProcessStage = this.viewer.scene.postProcessStages.add(
      new Cesium.PostProcessStage({
        fragmentShader: shader,
        uniforms: {
          intensity: this.rainConfig.intensity,
          speed: this.rainConfig.speed,
          density: this.rainConfig.density,
          size: this.rainConfig.size,
          windX: this.rainConfig.windX,
          windY: this.rainConfig.windY,
          range: this.rainConfig.range,
          height: this.rainConfig.height,
          streakLength: this.rainConfig.streakLength,
          inverses: inverses,       // 多个位置的逆矩阵数组
          positionCount: inverses.length  // 位置数量
        }
      })
    );
  }

  /**
   * 获取雨效果的着色器代码
   */
  getRainShader() {
    return `
            uniform sampler2D colorTexture;
            uniform sampler2D depthTexture;
            in vec2 v_textureCoordinates;
            uniform mat4 inverses[10];  // 最多支持10个降雨区域
            uniform int positionCount;  // 实际降雨区域数量
            uniform float intensity;
            uniform float speed;
            uniform float density;
            uniform float size;
            uniform float windX;
            uniform float windY;
            uniform float range;
            uniform float height;
            uniform float streakLength;
            
            // 噪声函数 - 用于生成雨滴随机分布
            float rand(vec2 co) {
                return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
            }
            
            // 雨滴形状函数 - 修复: 将参数名'length'改为'dropLength'避免与GLSL内置函数冲突
            float rainDrop(vec2 uv, vec2 pos, float dropSize, float dropLength) {
                // 雨滴主形状
                vec2 localUV = uv - pos;
                float drop = smoothstep(dropSize, 0.0, length(localUV));
                
                // 雨滴拖尾
                float tail = 0.0;
                if (localUV.y < 0.0) {
                    float tailShape = 1.0 - (abs(localUV.y) / dropLength);
                    tailShape *= smoothstep(dropSize * 0.5, 0.0, abs(localUV.x));
                    tail = tailShape * (1.0 - (abs(localUV.y) / dropLength));
                }
                
                return max(drop, tail) * 0.8;
            }
            
            // 检查点是否在降雨范围内
            bool isInRainRange(vec3 worldPos, mat4 inverseMatrix, float range, float height) {
                vec4 localPos = inverseMatrix * vec4(worldPos, 1.0);
                return length(localPos.xy) < range && localPos.z > 0.0 && localPos.z < height;
            }
            
            precision highp float;
            
            void main() {
                vec4 color = texture(colorTexture, v_textureCoordinates);
                float depth = czm_unpackDepth(texture(depthTexture, v_textureCoordinates));
                
                // 计算世界坐标 (修复: 使用Cesium 1.130.0兼容的坐标转换方法)
                vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth);
                vec3 worldPos = czm_inverseView * eyeCoordinate;
                worldPos /= worldPos.w;
                
                // 雨滴动画时间
                float time = czm_frameNumber * 0.05 * speed;
                
                // 雨滴累积效果
                float totalRain = 0.0;
                int drops = int(density * 100.0);
                
                // 对每个降雨区域计算雨滴效果
                for (int p = 0; p < 10; p++) {
                    if (p >= positionCount) break;
                    
                    // 检查当前点是否在该降雨区域内
                    if (isInRainRange(worldPos, inverses[p], range, height)) {
                        // 生成多个雨滴
                        for (int i = 0; i < 100; i++) {
                            if (i >= drops) break;
                            
                            // 随机位置和参数（结合区域索引确保不同区域雨滴分布不同）
                            float seedX = rand(vec2(float(i) + float(p) * 100.0, 45.123));
                            float seedY = rand(vec2(float(i) + float(p) * 100.0, 92.456));
                            
                            // 雨滴位置（带动画）
                            vec2 dropPos = vec2(
                                fract(seedX + windX * time * 0.1) * 2.0 - 1.0,
                                fract(seedY - time * 0.1) * 2.0 - 1.0
                            );
                            
                            // 基于深度的可见性衰减
                            float depthFactor = smoothstep(0.0, 1.0, 1.0 - depth);
                            
                            // 累积雨滴效果 - 修复: 传递正确参数名
                            totalRain += rainDrop(
                                v_textureCoordinates * 2.0 - 1.0, 
                                dropPos, 
                                size * 0.01 * depthFactor,
                                streakLength * 0.01 * depthFactor
                            );
                        }
                    }
                }
                
                // 应用雨滴到最终颜色
                totalRain = clamp(totalRain * intensity, 0.0, 1.0);
                vec3 rainColor = vec3(0.85, 0.9, 0.95) * totalRain;
                color.rgb = mix(color.rgb, rainColor, totalRain * 0.7);
                
                // 增加一些环境光散射效果
                color.rgb = mix(color.rgb, vec3(0.1, 0.15, 0.2) * totalRain * 0.3, 0.5);
                
                out_FragColor = color;
            }
        `;
  }

  /**
   * 创建GUI控制面板
   */
  createGuiControls() {
    this.gui = new dat.GUI();

    // 雨强度控制面板
    const intensityFolder = this.gui.addFolder('雨强度');
    intensityFolder.add(this.rainConfig, 'intensity', 0, 2, 0.1)
      .onChange(value => this.postProcessStage.uniforms.intensity = value);
    intensityFolder.add(this.rainConfig, 'density', 0.001, 0.1, 0.001)
      .onChange(value => this.postProcessStage.uniforms.density = value);
    intensityFolder.open();

    // 雨滴参数控制面板
    const dropFolder = this.gui.addFolder('雨滴参数');
    dropFolder.add(this.rainConfig, 'size', 0.1, 5, 0.1)
      .onChange(value => this.postProcessStage.uniforms.size = value);
    dropFolder.add(this.rainConfig, 'streakLength', 1, 50, 1)
      .onChange(value => this.postProcessStage.uniforms.streakLength = value);
    dropFolder.open();

    // 运动参数控制面板
    const motionFolder = this.gui.addFolder('运动参数');
    motionFolder.add(this.rainConfig, 'speed', 1, 50, 1)
      .onChange(value => this.postProcessStage.uniforms.speed = value);
    motionFolder.add(this.rainConfig, 'windX', -10, 10, 0.1)
      .onChange(value => this.postProcessStage.uniforms.windX = value);
    motionFolder.add(this.rainConfig, 'windY', -10, 10, 0.1)
      .onChange(value => this.postProcessStage.uniforms.windY = value);
    motionFolder.open();

    // 范围控制面板
    const rangeFolder = this.gui.addFolder('范围');
    rangeFolder.add(this.rainConfig, 'range', 1000, 20000, 100)
      .onChange(value => this.postProcessStage.uniforms.range = value);
    rangeFolder.add(this.rainConfig, 'height', 500, 5000, 100)
      .onChange(value => this.postProcessStage.uniforms.height = value);
    rangeFolder.open();
  }

  /**
   * 飞行到初始位置（第一个位置）
   */
  flyToInitialPosition() {
    if (this.config.positions.length > 0) {
      this.viewer.camera.flyTo({
        destination: this.config.positions[0],
        orientation: {
          heading: Cesium.Math.toRadians(0.0),
          pitch: Cesium.Math.toRadians(-90),
          roll: 0.0,
        },
        duration: this.config.flyToDuration,
      });
    }
  }

  /**
   * 销毁实例，释放资源
   */
  destroy() {
    if (this.postProcessStage) {
      this.viewer.scene.postProcessStages.remove(this.postProcessStage);
    }

    if (this.gui) {
      this.gui.destroy();
      this.gui = null;
    }
  }

  /**
   * 获取Cesium Viewer实例
   */
  getViewer() {
    return this.viewer;
  }

  /**
   * 更新降雨位置数组
   * @param {Array} positions - 新的位置数组
   */
  updatePositions(positions) {
    if (!Array.isArray(positions)) {
      positions = [positions];
    }
    this.config.positions = positions;

    // 更新逆矩阵数组
    const inverses = this.config.positions.map(position =>
      Cesium.Matrix4.inverse(
        Cesium.Transforms.eastNorthUpToFixedFrame(position),
        new Cesium.Matrix4()
      )
    );

    this.postProcessStage.uniforms.inverses = inverses;
    this.postProcessStage.uniforms.positionCount = inverses.length;
  }

  /**
   * 添加一个新的降雨位置
   * @param {Cesium.Cartesian3} position - 要添加的位置
   */
  addPosition(position) {
    this.config.positions.push(position);
    this.updatePositions(this.config.positions);
  }

  /**
   * 移除指定索引的降雨位置
   * @param {number} index - 要移除的位置索引
   */
  removePosition(index) {
    if (index >= 0 && index < this.config.positions.length) {
      this.config.positions.splice(index, 1);
      this.updatePositions(this.config.positions);
    }
  }
}

// 导出模块
if (typeof window !== 'undefined' && typeof window.exports === 'undefined') {
  window.CesiumRainEffect = CesiumRainEffect;
}

if (typeof module !== 'undefined' && module.exports) {
  module.exports = CesiumRainEffect;
}

export default CesiumRainEffect;